package com.example.weblending.controlller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.weblending.domain.File;
import com.example.weblending.domain.FileResult;
import com.example.weblending.domain.User;
import com.example.weblending.domain.statistics.StatisticsField;
import com.example.weblending.exception.GlobalException;
import com.example.weblending.service.AnalyzeService;
import com.example.weblending.service.FileService;
import com.example.weblending.service.TaskService;
import com.example.weblending.service.UserService;
import com.example.weblending.utils.JwtUtils;
import com.example.weblending.utils.Result;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/analyze")
@CrossOrigin
public class AnalyzeController {
    @Resource
    private AnalyzeService analyzeService;

    @Resource
    private FileService fileService;

    @Resource
    private TaskService taskService;

    @Resource
    private UserService userService;


    /**
     * 获得分析结果的列表，实现上只返回查到的第一条数据
     * 先通过用户自身id获得 自己上传的文件列表 分页查询
     * 再对查询到的文件列表取第一个获得在数据库保存的分析结果
     * 并向前端返回 result:分页信息
     *             condition: 将不同条件按位编码并缓存的统计结果
     *             sort: 最值产生的条件按位编码
     */
    @GetMapping("result/{page}/{limit}")
    public Result getResult(@PathVariable long page, @PathVariable long limit, HttpServletRequest request) {
        //检查用户登录信息是否有效
        boolean v=JwtUtils.checkToken(request);
        if(!v){
            throw new GlobalException(20004,"请重新登录");
        }
        String id = JwtUtils.getMemberIdByJwtToken(request);
        //查询文件获得分页结果
        Page<File> files=fileService.getListById(page,limit,id);
        //获得第一个文件的分析结果
        FileResult result=analyzeService.getResult(files);
        //获得的object是 每个条件自己的趋势，因为保存的是数组json字符串，因此依然需要再次转一次
        JSONObject object=JSON.parseObject(result.getFieldStatistic());
        JSONObject res=new JSONObject();
        for (String key:object.keySet()){
            res.put(key, JSONArray.parseArray(object.getString(key)));
        }
        //向前台返回的信息
        return Result.ok()
                //分页信息
                .data(files)
                //每个条件自己的成功率趋势数组
                .data("result",res)
                //条件按位编码缓存的统计值
                .data("condition", JSONObject.parseObject(result.getFullStatistic(),new TypeReference<Map<Integer, StatisticsField>>(){}))
                //产生最值的条件编码
                .data("sort", JSONArray.parseArray(result.getSortStatistic()));
    }

    /**
     * 获得指定文件的详细信息
     */
    @GetMapping("info/{id}")
    public Result getInfo(@PathVariable int id,HttpServletRequest request) {
        //检查登录信息是否有效
        boolean v=JwtUtils.checkToken(request);
        if(!v){
            throw new GlobalException(20004,"请重新登录");
        }
        //获得文件的信息
        File file=fileService.getById(id);
        //获得文件的分析结果
        FileResult result= analyzeService.getById(id);
        //获得的object是 每个条件自己的趋势，因为保存的是数组json字符串，因此依然需要再次转一次
        JSONObject object=JSON.parseObject(result.getFieldStatistic());
        JSONObject res=new JSONObject();
        for (String key:object.keySet()){
            res.put(key, JSONArray.parseArray(object.getString(key)));
        }

        return Result.ok()
                //文件的自身信息
                .data("basic",file)
                //每个条件自己的成功率趋势数组
                .data("result",res)
                //条件按位编码缓存的统计值
                .data("condition", JSONObject.parseObject(result.getFullStatistic(),new TypeReference<Map<Integer, StatisticsField>>(){}))
                //产生最值的条件编码
                .data("sort",JSONArray.parseArray( result.getSortStatistic()));
    }

    /**
     * 清洗文件
     * 由于清洗时间过长，在触发清洗任务成功后直接向前台发送执行成功的信息
     * 由于任务执行时间过长，使用task 表来记录该任务开始执行
     */
    @PostMapping("clean/{id}")
    public Result clean(@PathVariable int id,HttpServletRequest request){
        //检查登录信息
        User user =JwtUtils.checkUser(request,userService);
        //获得要分析的文件信息
        File file= fileService.getById(id);
        //检查前置条件，如文件自身的状态，用户的清洗次数，当前清洗任务是否已经开始
        analyzeService.cleanCheck(file,user);
        //新增一条 task来记录本次清洗任务
        int taskId=taskService.quickCleanTask(user.getUid());
        //保存到当前文件正在执行的任务
        file.setTask(taskId);
        fileService.updateById(file);
        //触发清洗任务
        analyzeService.clean(file,user);
        //向前端发送开始执行任务信息
        return Result.ok().data("task",id);
    }

    /**
     * 分析文件
     * 由于分析时间过长，在触发分析任务成功后直接向前台发送执行成功的信息
     * 由于任务执行时间过长，使用task 表来记录该任务开始执行
     */
    @PostMapping("exec/{id}")
    public Result analyze(@PathVariable int id,HttpServletRequest request){
        //检查登录信息
        User user =JwtUtils.checkUser(request,userService);
        //获得要分析的文件信息
        File file= fileService.getById(id);
        //检查前置条件，如文件自身的状态，用户的分析次数，当前分析任务是否已经开始
        analyzeService.analyzeCheck(file,user);
        //新增一条 task来记录本次分析任务
        int taskId=taskService.quickAnalyzeTask(user.getUid());
        //保存到当前文件正在执行的任务
        file.setTask(taskId);
        fileService.updateById(file);
        //触发分析任务
        analyzeService.analyze(file,user);
        //向前端发送开始执行任务信息
        return Result.ok().data("task",id);
    }
}
